import type { IconId } from '../../../icons/types/interfaces'
import type { NavbarThemeVarConfig } from './component/navbar'
import type { BadgeThemeVarBaseConfig, BadgeThemeVarConfig } from './service/badge/types'
import type { ThemeVarBaseConfig } from './service/base'
import type { ButtonThemeVarConfig } from './service/button/types'
import type { InputThemeVarConfig } from './service/input/types'
import type { LinkThemeVarConfig } from './service/link/types'
import type { TagThemeVarConfig } from './service/tag/types'
import type {
  AnswerThemeVarConfig,
  BlogThemeVarConfig,
  DefaultThemeVarConfig,
  EmThemeVarConfig,
  MessageThemeVarConfig,
  PageBarThemeVarConfig,
  SearchThemeVarConfig,
  TabThemeVarConfig,
  ThemeVarConfig,
  ThemeVarIconConfig,
  TieBarThemeVarConfig,
  TitleThemeVarConfig,
} from './types'
import { ActionThemeVarService } from './action'
import { NavbarThemeVarService } from './component/navbar'
import { BadgeThemeVarService } from './service/badge'
import { BaseThemeVarService } from './service/base'
import { ButtonThemeVarService } from './service/button'
import { LinkThemeVarService } from './service/link'
import { TagThemeVarService } from './service/tag'
import {
  ThemeElement,
  ThemeProperty,
  ThemeState,
  ThemeStatus,
} from './types'

export class ThemeVarService extends BaseThemeVarService {
  private static instance: ThemeVarService
  private readonly actionService: ActionThemeVarService = ActionThemeVarService.getInstance()
  private readonly badgeService: BadgeThemeVarService = BadgeThemeVarService.getInstance()
  private readonly buttonService: ButtonThemeVarService = ButtonThemeVarService.getInstance()
  private readonly tagService: TagThemeVarService = TagThemeVarService.getInstance()
  private readonly linkService: LinkThemeVarService = LinkThemeVarService.getInstance()
  private readonly navbarService: NavbarThemeVarService = NavbarThemeVarService.getInstance()

  static getInstance(): ThemeVarService {
    if (!ThemeVarService.instance) {
      ThemeVarService.instance = new ThemeVarService()
    }
    return ThemeVarService.instance
  }

  generateIcon(id: IconId): string {
    return this.varMapper.getVarName({
      element: ThemeElement.Icon,
      postModifier: id,
    })
  }

  get icon(): ThemeVarIconConfig {
    return {
      default: this.varMapper.getVarName({
        element: ThemeElement.Icon,
        property: ThemeProperty.Bg,
      }),
      hover: this.varMapper.getVarName({
        element: ThemeElement.Icon,
        property: ThemeProperty.Bg,
        state: ThemeState.Hover,
      }),
      active: this.varMapper.getVarName({
        element: ThemeElement.Icon,
        property: ThemeProperty.Bg,
        state: ThemeState.Active,
      }),
      disabled: this.varMapper.getVarName({
        element: ThemeElement.Icon,
        property: ThemeProperty.Bg,
        state: ThemeState.Disabled,
      }),
    }
  }

  get selection(): ThemeVarBaseConfig {
    return this.actionService.selection
  }

  get input(): InputThemeVarConfig {
    return {
      default: {
        background: this.default.background.base,
        border: this.default.border.colorNeutral,
        borderHover: this.default.border.colorActive,
        color: this.varMapper.getVarValue({
          element: ThemeElement.Text,
          property: ThemeProperty.Text,
        }),
        caret: this.varMapper.getVarValue({
          element: ThemeElement.Text,
          subElement: 'caret',
        }),
      },
    }
  }

  get badge(): BadgeThemeVarConfig {
    return this.badgeService.default
  }

  get upvote(): BadgeThemeVarBaseConfig {
    return this.badgeService.green
  }

  get liked(): BadgeThemeVarBaseConfig {
    return this.badgeService.red
  }

  get button(): ButtonThemeVarConfig {
    return this.buttonService.default
  }

  get tag(): TagThemeVarConfig {
    return this.tagService.default
  }

  get link(): LinkThemeVarConfig {
    return this.linkService.default
  }

  get navbar(): NavbarThemeVarConfig {
    return this.navbarService.default
  }

  get default(): DefaultThemeVarConfig {
    return {
      base: {
        primary: this.varMapper.getVarName({
          postModifier: 'primary',
        }),
      },
      style: {
        margin: '10px',
        padding: '15px',
        borderRadius: '8px',
      },
      text: {
        base: this.varMapper.getVarName({
          property: ThemeProperty.Text,
          postModifier: 'base',
        }),
        primary: this.varMapper.getVarName({
          property: ThemeProperty.Text,
          postModifier: 'primary',
        }),
        secondary: this.varMapper.getVarName({
          property: ThemeProperty.Text,
          postModifier: 'secondary',
        }),
        hint: this.varMapper.getVarName({
          property: ThemeProperty.Text,
          postModifier: 'hint',
        }),
        neutral: this.varMapper.getVarName({
          property: ThemeProperty.Text,
          postModifier: 'neutral',
        }),
      },
      background: {
        base: this.varMapper.getVarName({
          property: ThemeProperty.Bg,
          postModifier: 'base',
        }),
        surface: this.varMapper.getVarName({
          property: ThemeProperty.Bg,
          postModifier: 'surface',
        }),
        overlay: this.varMapper.getVarName({
          property: ThemeProperty.Bg,
          postModifier: 'overlay',
        }),
        preview: this.varMapper.getVarName({
          property: ThemeProperty.Bg,
          postModifier: 'preview',
        }),
        highlight: this.varMapper.getVarName({
          property: ThemeProperty.Bg,
          postModifier: 'highlight',
        }),
        fixed: this.varMapper.getVarName({
          property: ThemeProperty.Bg,
          postModifier: 'fixed',
        }),
        list: this.varMapper.getVarName({
          property: ThemeProperty.Bg,
          postModifier: 'list',
        }),
        left: this.varMapper.getVarName({
          property: ThemeProperty.Bg,
          postModifier: 'left',
        }),
        right: this.varMapper.getVarName({
          property: ThemeProperty.Bg,
          postModifier: 'right',
        }),
      },
      border: {
        colorPrimary: this.varMapper.getVarName({
          property: ThemeProperty.Border,
          postModifier: 'primary',
        }),
        colorNeutral: this.varMapper.getVarName({
          property: ThemeProperty.Border,
          postModifier: 'neutral',
        }),
        colorActive: this.varMapper.getVarName({
          property: ThemeProperty.Border,
          postModifier: 'active',
        }),
      },
      shadow: {
        sm: this.varMapper.getVarName({
          property: ThemeProperty.Shadow,
          postModifier: 'sm',
        }),
        hover: this.varMapper.getVarName({
          property: ThemeProperty.Shadow,
          postModifier: 'hover',
        }),
      },
    }
  }

  get title(): TitleThemeVarConfig {
    return {
      default: {
        primary: this.default.text.primary,
      },
    }
  }

  get message(): MessageThemeVarConfig {
    return {
      success: {
        textPrimary: this.varMapper.getVarName({
          status: ThemeStatus.Success,
          property: ThemeProperty.Text,
        }),
        textSecondary: this.varMapper.getVarName({
          status: ThemeStatus.Success,
          property: ThemeProperty.Text,
          modifier: 'secondary',
        }),
      },
      warning: {
        textPrimary: this.varMapper.getVarName({
          status: ThemeStatus.Warning,
          property: ThemeProperty.Text,
        }),
        textSecondary: this.varMapper.getVarName({
          status: ThemeStatus.Warning,
          property: ThemeProperty.Text,
          modifier: 'secondary',
        }),
      },
      error: {
        textPrimary: this.varMapper.getVarName({
          status: ThemeStatus.Danger,
          property: ThemeProperty.Text,
        }),
        textSecondary: this.varMapper.getVarName({
          status: ThemeStatus.Danger,
          property: ThemeProperty.Text,
          modifier: 'secondary',
        }),
      },
      danger: {
        textPrimary: this.varMapper.getVarName({
          status: ThemeStatus.Danger,
          property: ThemeProperty.Text,
        }),
        textSecondary: this.varMapper.getVarName({
          status: ThemeStatus.Danger,
          property: ThemeProperty.Text,
          modifier: 'secondary',
        }),
      },
      info: {
        textPrimary: this.varMapper.getVarName({
          status: ThemeStatus.Info,
          property: ThemeProperty.Text,
        }),
        textSecondary: this.varMapper.getVarName({
          status: ThemeStatus.Info,
          property: ThemeProperty.Text,
          modifier: 'secondary',
        }),
      },
      orange: {
        textPrimary: this.varMapper.getVarName({
          status: ThemeStatus.Orange,
          property: ThemeProperty.Text,
        }),
        textSecondary: this.varMapper.getVarName({
          status: ThemeStatus.Orange,
          property: ThemeProperty.Text,
          modifier: 'secondary',
        }),
      },
      purple: {
        textPrimary: this.varMapper.getVarName({
          status: ThemeStatus.Purple,
          property: ThemeProperty.Text,
        }),
        textSecondary: this.varMapper.getVarName({
          status: ThemeStatus.Purple,
          property: ThemeProperty.Text,
          modifier: 'secondary',
        }),
      },
    }
  }

  get em(): EmThemeVarConfig {
    return {
      text: this.varMapper.getVarName(
        { element: ThemeElement.Em, property: ThemeProperty.Text },
      ),
      textHover: this.varMapper.getVarName(
        { element: ThemeElement.Em, property: ThemeProperty.Text, state: ThemeState.Hover },
      ),
    }
  }

  get pageBar(): PageBarThemeVarConfig {
    return {
      default: {
        border: '3px solid transparent',
        borderRadius: '9px',
        fontSize: '14px',
        height: '36px',
        gap: '10px',
      },
      button: {
        padding: '5px',
      },
      currentPage: {
        bg: this.varMapper.getVarName({
          element: ThemeElement.PageBar,
          subElement: 'current-page',
          property: ThemeProperty.Bg,
        }),
        text: this.varMapper.getVarName({
          element: ThemeElement.PageBar,
          subElement: 'current-page',
          property: ThemeProperty.Text,
        }),
      },
      otherPage: {
        bg: this.varMapper.getVarName({
          element: ThemeElement.PageBar,
          subElement: 'other-page',
          property: ThemeProperty.Bg,
        }),
        bgHover: this.varMapper.getVarName({
          element: ThemeElement.PageBar,
          subElement: 'other-page',
          property: ThemeProperty.Bg,
          state: ThemeState.Hover,
        }),
        text: this.varMapper.getVarName({
          element: ThemeElement.PageBar,
          subElement: 'other-page',
          property: ThemeProperty.Text,
        }),
        textHover: this.varMapper.getVarName({
          element: ThemeElement.PageBar,
          subElement: 'other-page',
          property: ThemeProperty.Text,
          state: ThemeState.Hover,
        }),
      },
    }
  }

  get tab(): TabThemeVarConfig {
    return {
      text: this.default.text.secondary,
      textActive: this.varMapper.getVarName({
        element: ThemeElement.Tab,
        property: ThemeProperty.Text,
        state: ThemeState.Active,
      }),
      textNeutral: this.default.text.neutral,
      textHover: this.link.default.text,
      bgFocus: this.varMapper.getVarName({
        element: ThemeElement.Tab,
        property: ThemeProperty.Bg,
        state: ThemeState.Focus,
      }),
      borderActive: this.varMapper.getVarName({
        element: ThemeElement.Tab,
        property: ThemeProperty.Border,
        state: ThemeState.Active,
      }),
      borderBottom: `3px solid var(${this.varMapper.getVarName({
        element: ThemeElement.Tab,
        property: ThemeProperty.Border,
        state: ThemeState.Active,
      })})`,
      fontSize: '14px',
    }
  }

  get answer(): AnswerThemeVarConfig {
    return {
      default: {
        background: this.varMapper.getVarName({
          element: ThemeElement.Answer,
          property: ThemeProperty.Bg,
        }),
      },
      switch: {
        mask: {
          text: this.varMapper.getVarName({
            element: ThemeElement.Answer,
            subElement: 'switch-mask',
            property: ThemeProperty.Text,
          }),
          background: this.varMapper.getVarName({
            element: ThemeElement.Answer,
            subElement: 'switch-mask',
            property: ThemeProperty.Bg,
          }),
        },
      },
      loading: {
        background: this.varMapper.getVarName({
          element: ThemeElement.Answer,
          subElement: 'loading',
          property: ThemeProperty.Bg,
        }),
      },
    }
  }

  /**
   * 【搜索平台】
   */
  get search(): SearchThemeVarConfig {
    return {
      default: {
        text: this.default.text.secondary,
        textBase: this.default.text.base,
        textPrimary: this.default.text.primary,
        textNeutral: this.default.text.neutral,
        background: this.default.background.base,
        fontSize: '16px',
      },
      inputBox: {
        border: '2px solid #205aef',
        borderTransparent: '2px solid transparent',
      },
      header: {
        background: this.navbar.default.background,
      },
      history: {
        text: this.varMapper.getVarName({
          element: ThemeElement.Search,
          subElement: 'history',
          property: ThemeProperty.Text,
        }),
      },
      suggestions: {
        text: this.varMapper.getVarName({
          element: ThemeElement.Search,
          subElement: 'suggestions',
          property: ThemeProperty.Text,
        }),
        fontWeight: '400',
      },
      resultItem: {
        background: this.varMapper.getVarName({
          element: ThemeElement.Search,
          subElement: 'result-item',
          property: ThemeProperty.Bg,
        }),
        backgroundOfficial: this.varMapper.getVarName({
          element: ThemeElement.Search,
          subElement: 'result-item',
          property: ThemeProperty.Bg,
          postModifier: 'official',
        }),
        backgroundPopular: this.varMapper.getVarName({
          element: ThemeElement.Search,
          subElement: 'result-item',
          property: ThemeProperty.Bg,
          postModifier: 'popular',
        }),
        shadow: this.varMapper.getVarName({
          element: ThemeElement.Search,
          subElement: 'result-item',
          property: ThemeProperty.Shadow,
        }),
        paddingStandard: '15px',
        padding: '15px 15px 48px 15px',
        borderRadius: '8px',
        gap: '20px',
        titleFontSize: '18px',
        noItemTip: this.message.warning.textPrimary,
      },
    }
  }

  /**
   * 【博客平台】
   */
  get blog(): BlogThemeVarConfig {
    return {}
  }

  /**
   * 【贴吧平台】
   */
  get tieBar(): TieBarThemeVarConfig {
    return {
      default: {
        text: this.default.text.secondary,
        textBase: this.default.text.base,
        textPrimary: this.default.text.primary,
        background: this.default.background.base,
        borderRadius: '8px',
        gap: '20px',
        padding: '15px',
      },
      header: {
        background: this.navbar.default.background,
      },
      answer: {
        background: this.varMapper.getVarName({
          element: ThemeElement.TieBar,
          subElement: 'answer',
          property: ThemeProperty.Bg,
        }),
      },
      comment: {
        background: this.varMapper.getVarName({
          element: ThemeElement.TieBar,
          subElement: 'comment',
          property: ThemeProperty.Bg,
        }),
      },
    }
  }

  /**
   * 动态获取变量名
   */
  getVar(config: ThemeVarConfig): string {
    return this.varMapper.getVarName(config)
  }
}
